package com.vne.skyemart.util;

import java.net.URL;

import javax.servlet.ServletContext;

import com.vne.skyemart.exception.KeyNotFoundException;

public class SkyemartConfig {
	private ServletContext servletContextInit = null;
	private static SkyemartConfig ourInstance = null;
	private static Config config = new Config();
	
	public static SkyemartConfig getInstance() {
		if (ourInstance == null) {
			ourInstance = new SkyemartConfig();
		}		
		return ourInstance;
	}

	public SkyemartConfig() {
		config.loadEnv();
		URL url = null;
		try {
			url = config.getClass().getResource("/skyemart_config.properties");
		} catch (Exception e) {
			url = null;
		}

		if (url == null) {
			try {
				url = config.getClass().getClassLoader().getResource("/skyemart_config.properties");
			} catch (Exception e) {
				url = null;
			}
		}
		
		if (url == null) {
			return;
		}

		String fileName = url.getFile();
		try {
			config.loadFile(fileName, false);
		} catch (Exception e) {
		}
	}

	/**
	 * 
	 * returns the string corresponding to the key passed in, or the default if
	 * a value is not found.
	 * 
	 * @param key
	 *            what config key to look for.
	 * @throws KeyNotFoundException
	 *             if the key doesnt exist.
	 * @throws NullPointerException
	 *             if AppConfig has not been initialized or if the key is null.
	 * @return value
	 */
	public String get(String key) throws KeyNotFoundException {
		return config.getProperty(key);
	}

	/**
	 * 
	 * returns the string corresponding to the key passed in.
	 * 
	 * @param key
	 *            what config key to look for.
	 * @throws NullPointerException
	 *             if AppConfig has not been initialized or if the key is null.
	 * @param defaultValue -
	 *            return this value if the key is null
	 * @return defauleValue
	 */
	public String get(String key, String defaultValue) {
		return config.getProperty(key, defaultValue);
	}

	/**
	 * Set value for a key
	 * @param key
	 * @param value
	 * @return
	 * @throws KeyNotFoundException
	 */
	public String set(String key, String value) throws KeyNotFoundException {
		return config.setProperty(key, value);
	}

	/**
	 * 
	 * returns true if the key has a value.
	 * 
	 * @param key
	 *            what config key to look for.
	 * @throws NullPointerException
	 *             if AppConfig has not been initialized or if the key is null.
	 * @return boolean
	 */
	public boolean hasProperty(String key) {
		return config.hasProperty(key);
	}

	/**
	 * get Boolean value of a key
	 * @param key
	 * @return
	 * @throws NullPointerException
	 * @throws NumberFormatException
	 * @throws KeyNotFoundException
	 */
	public boolean getBoolean(String key) throws NullPointerException,
			NumberFormatException, KeyNotFoundException {
		return getBooleanValue(config.getProperty(key));
	}

	/**
	 * get Boolean value of a key, if null, get the default value
	 * @param key
	 * @param defaultValue
	 * @return
	 * @throws NullPointerException
	 * @throws NumberFormatException
	 */
	public boolean getBoolean(String key, String defaultValue)
			throws NullPointerException, NumberFormatException {
		return getBooleanValue(config.getProperty(key, defaultValue));
	}

	/**
	 * get char value of a key
	 * @param key
	 * @return
	 * @throws NullPointerException
	 * @throws NumberFormatException
	 * @throws KeyNotFoundException
	 */
	public char getChar(String key) throws NullPointerException,
			NumberFormatException, KeyNotFoundException {
		return getCharValue(config.getProperty(key));
	}

	/**
	 * 
	 * @param key
	 * @param defaultValue
	 * @return
	 * @throws NullPointerException
	 * @throws NumberFormatException
	 */
	public char getChar(String key, String defaultValue)
			throws NullPointerException, NumberFormatException {
		return getCharValue(config.getProperty(key, defaultValue));
	}

	/**
	 * 
	 * @param key
	 * @return
	 * @throws NullPointerException
	 * @throws NumberFormatException
	 * @throws KeyNotFoundException
	 */
	public short getShort(String key) throws NullPointerException,
			NumberFormatException, KeyNotFoundException {
		return getShortValue(config.getProperty(key));
	}

	public short getShort(String key, String defaultValue)
			throws NullPointerException, NumberFormatException {
		return getShortValue(config.getProperty(key, defaultValue));
	}

	/**
	 * 
	 * @param key
	 * @return
	 * @throws NullPointerException
	 * @throws NumberFormatException
	 * @throws KeyNotFoundException
	 */
	public int getInteger(String key) throws NullPointerException,
			NumberFormatException, KeyNotFoundException {
		return getIntegerValue(config.getProperty(key));
	}

	public int getInteger(String key, String defaultValue)
			throws NullPointerException, NumberFormatException {
		return getIntegerValue(config.getProperty(key, defaultValue));
	}

	/**
	 * 
	 * @param key
	 * @return
	 * @throws NullPointerException
	 * @throws NumberFormatException
	 * @throws KeyNotFoundException
	 */
	public long getLong(String key) throws NullPointerException,
			NumberFormatException, KeyNotFoundException {
		return getLongValue(config.getProperty(key));
	}

	public long getLong(String key, String defaultValue)
			throws NullPointerException, NumberFormatException {
		return getLongValue(config.getProperty(key, defaultValue));
	}

	/**
	 * 
	 * @param key
	 * @return
	 * @throws NullPointerException
	 * @throws NumberFormatException
	 * @throws KeyNotFoundException
	 */
	public  float getFloat(String key) throws NullPointerException,
			NumberFormatException, KeyNotFoundException {
		return getFloatValue(config.getProperty(key));
	}

	/**
	 * 
	 * @param key
	 * @param defaultValue
	 * @return
	 * @throws NullPointerException
	 * @throws NumberFormatException
	 */
	public float getFloat(String key, String defaultValue)
			throws NullPointerException, NumberFormatException {
		return getFloatValue(config.getProperty(key, defaultValue));
	}

	/**
	 * 
	 * @param key
	 * @return
	 * @throws NullPointerException
	 * @throws NumberFormatException
	 * @throws KeyNotFoundException
	 */
	public double getDouble(String key) throws NullPointerException,
			NumberFormatException, KeyNotFoundException {
		return getDoubleValue(config.getProperty(key));
	}

	/**
	 * 
	 * @param key
	 * @param defaultValue
	 * @return
	 * @throws NullPointerException
	 * @throws NumberFormatException
	 */
	public double getDouble(String key, String defaultValue)
			throws NullPointerException, NumberFormatException {
		return getDoubleValue(config.getProperty(key, defaultValue));
	}

	private void checkNull(String s) throws NullPointerException {
		if (s == null) {
			throw new NullPointerException("cannot convert null");
		}
	}

	private boolean getBooleanValue(String s)
			throws NullPointerException, NumberFormatException {
		checkNull(s);
		if (s.equalsIgnoreCase("true") || s.equalsIgnoreCase("yes")
				|| s.equalsIgnoreCase("enable") || s.equalsIgnoreCase("y")
				|| s.equalsIgnoreCase("t") || s.equalsIgnoreCase("1")) {
			return true;
		}
		
		if (s.equalsIgnoreCase("false") || s.equalsIgnoreCase("no")
				|| s.equalsIgnoreCase("disable") || s.equalsIgnoreCase("n")
				|| s.equalsIgnoreCase("f") || s.equalsIgnoreCase("0")) {
			return false;
		}
		
		try {
			long lval = Long.parseLong(s);
			return lval != 0;
		} catch (NumberFormatException nef) {
			throw new NumberFormatException("cannot convert to boolean: " + s);
		}
	}

	private char getCharValue(String s) throws NumberFormatException, NullPointerException {
		checkNull(s);
		if (s.length() != 1) {
			throw new NumberFormatException("which char did you want from this string: " + s);
		}
		
		return s.charAt(0);
	}

	private short getShortValue(String s) throws NumberFormatException, NullPointerException {
		checkNull(s);
		return Short.parseShort(s);
	}

	private int getIntegerValue(String s) throws NumberFormatException, NullPointerException {
		checkNull(s);
		return Integer.parseInt(s);
	}

	private long getLongValue(String s) throws NumberFormatException, NullPointerException {
		checkNull(s);
		return Long.parseLong(s);
	}

	private float getFloatValue(String s) throws NumberFormatException, NullPointerException {
		checkNull(s);
		return Float.parseFloat(s);
	}

	private double getDoubleValue(String s) throws NumberFormatException, NullPointerException {
		checkNull(s);
		return Double.parseDouble(s);
	}

	/**
	 * @return the servletContextInit
	 */
	public ServletContext getServletContextInit() {
		return servletContextInit;
	}

	/**
	 * @param servletContextInit the servletContextInit to set
	 */
	public void setServletContextInit(ServletContext servletContextInit) {
		this.servletContextInit = servletContextInit;
	}
}
